#include "ring_buffer.h"
#include <string.h>

#define MIN(a, b) ((a) < (b) ? (a) : (b))

int ring_buffer_init(ring_buffer_t* rb, uint8_t* buffer, int32_t size) {
    if (!rb || !buffer || size <= 0) {
        return -1;
    }

    rb->buffer = buffer;
    rb->size = size;
    rb->wpos = 0;
    rb->rpos = 0;
    pthread_mutex_init(&rb->mutex, NULL);
    
    return 0;
}

void ring_buffer_deinit(ring_buffer_t* rb) {
    if (!rb) return;
    
    pthread_mutex_destroy(&rb->mutex);
    memset(rb, 0, sizeof(ring_buffer_t));
}

void ring_buffer_reset(ring_buffer_t* rb) {
    if (!rb) return;
    
    pthread_mutex_lock(&rb->mutex);
    rb->wpos = 0;
    rb->rpos = 0;
    pthread_mutex_unlock(&rb->mutex);
}

int32_t ring_buffer_write(ring_buffer_t* rb, const uint8_t* data, int32_t len) 
{
    int32_t available = 0;
    int write_len = 0;
    int to_end = 0;

    if (!rb || !data || len <= 0) {
        return RB_ERROR;
    }

    pthread_mutex_lock(&rb->mutex);
    available = ring_buffer_available(rb);
    if (0 == available) {
        pthread_mutex_unlock(&rb->mutex);
        return RB_FULL;
    }

    write_len = MIN(len, available);
    to_end = rb->size - rb->wpos;
    
    if (write_len <= to_end) {
        memcpy(rb->buffer + rb->wpos, data, write_len);
        rb->wpos += write_len;
        if (rb->wpos == rb->size) {
            rb->wpos = 0;
        }
    } else {
        memcpy(rb->buffer + rb->wpos, data, to_end);
        memcpy(rb->buffer, data + to_end, write_len - to_end);
        rb->wpos = write_len - to_end;
    }
    
    pthread_mutex_unlock(&rb->mutex);
    return write_len;
}

int32_t ring_buffer_read(ring_buffer_t* rb, uint8_t* data, int32_t len) 
{
    int32_t used = 0;
    int32_t read_len = 0;
    int32_t to_end = 0;


    if (!rb || !data || len <= 0) {
        return RB_ERROR;
    }

    pthread_mutex_lock(&rb->mutex);
    used = ring_buffer_used(rb);
    if (used == 0) {
        pthread_mutex_unlock(&rb->mutex);
        return RB_EMPTY;
    }
    
    read_len = MIN(len, used);
    to_end = rb->size - rb->rpos;
    
    if (read_len <= to_end) {
        memcpy(data, rb->buffer + rb->rpos, read_len);
        rb->rpos += read_len;
        if (rb->rpos == rb->size) {
            rb->rpos = 0;
        }
    } else {
        memcpy(data, rb->buffer + rb->rpos, to_end);
        memcpy(data + to_end, rb->buffer, read_len - to_end);
        rb->rpos = read_len - to_end;
    }
    
    pthread_mutex_unlock(&rb->mutex);
    return read_len;
}

int32_t ring_buffer_used(ring_buffer_t* rb) {
    if (!rb) return -1;
    
    int32_t used = rb->wpos - rb->rpos;
    if (used < 0) {
        used += rb->size;
    }
    
    // 确保最多只能使用size-1
    return used;
}

int32_t ring_buffer_available(ring_buffer_t* rb) {
 //   if (!rb) return -1;
    
    int32_t used = ring_buffer_used(rb);
    return rb->size - 1 - used;
}

int ring_buffer_is_empty(ring_buffer_t* rb) {
   // if (!rb) return -1;
    
    pthread_mutex_lock(&rb->mutex);
    int empty = (rb->wpos == rb->rpos);
    pthread_mutex_unlock(&rb->mutex);
    
    return empty;
}

int ring_buffer_is_full(ring_buffer_t* rb) {
    //if (!rb) return -1;
    
    return (ring_buffer_available(rb) == 0);
}